
import logging
from django.utils import timezone
from django.db import transaction
from django.shortcuts import get_object_or_404
from django.contrib.auth import get_user_model

from rest_framework import status, viewsets, mixins
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.decorators import action

from .models import UserProfile
from .serializers import (
    UserSerializer, UserUpdateSerializer,
    UserProfileSerializer, UserProfileUpdateSerializer,
    ChangePasswordSerializer, ResetPasswordSerializer,
    BindPhoneSerializer
)
from auth_app.models import SmsVerification

User = get_user_model()
logger = logging.getLogger(__name__)


class UserViewSet(viewsets.GenericViewSet,
                  mixins.RetrieveModelMixin,
                  mixins.UpdateModelMixin,
                  mixins.ListModelMixin):
    """
    用户管理API
    
    提供用户信息的查询、更新、密码管理等功能
    
    * 获取用户列表 - GET /api/users/
    * 获取单个用户 - GET /api/users/{id}/
    * 更新用户信息 - PUT/PATCH /api/users/{id}/
    * 获取用户详细资料 - GET /api/users/{id}/profile/
    * 更新用户详细资料 - PUT/PATCH /api/users/{id}/update_profile/
    * 修改密码 - POST /api/users/{id}/change_password/
    * 重置密码 - POST /api/users/reset_password/
    * 绑定手机号 - POST /api/users/{id}/bind_phone/
    
    使用 'me' 作为用户ID可以操作当前登录用户: /api/users/me/
    """
    
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]
    
    def get_serializer_class(self):
        """根据操作选择序列化器"""
        if self.action == 'update' or self.action == 'partial_update':
            return UserUpdateSerializer
        elif self.action == 'update_profile':
            return UserProfileUpdateSerializer
        elif self.action == 'change_password':
            return ChangePasswordSerializer
        elif self.action == 'reset_password':
            return ResetPasswordSerializer
        elif self.action == 'bind_phone':
            return BindPhoneSerializer
        return self.serializer_class
    
    def get_permissions(self):
        """根据操作选择权限"""
        if self.action == 'reset_password':
            return [AllowAny()]
        return super().get_permissions()
    
    def get_object(self):
        """获取当前用户对象"""
        if self.kwargs.get('pk') == 'me':
            return self.request.user
        return super().get_object()
    
    @action(detail=True, methods=['get'])
    def profile(self, request, pk=None):
        """获取用户详细资料"""
        user = self.get_object()
        
        # 获取或创建用户详细资料
        profile, created = UserProfile.objects.get_or_create(user=user)
        
        serializer = UserProfileSerializer(profile)
        return Response(serializer.data)
    
    @action(detail=True, methods=['put', 'patch'])
    def update_profile(self, request, pk=None):
        """更新用户详细资料"""
        user = self.get_object()
        
        # 获取或创建用户详细资料
        profile, created = UserProfile.objects.get_or_create(user=user)
        
        serializer = self.get_serializer(profile, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def change_password(self, request, pk=None):
        """
        修改用户密码
        ---
        parameters:
          - name: old_password
            description: 用户当前密码
            required: true
            type: string
          - name: new_password
            description: 用户新密码
            required: true
            type: string
        responses:
          200:
            description: 密码修改成功
          400:
            description: 请求数据无效
          401:
            description: 旧密码验证失败
        """
        user = self.get_object()
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        old_password = serializer.validated_data.get('old_password')
        new_password = serializer.validated_data.get('new_password')
        
        # 验证旧密码
        if not user.check_password(old_password):
            return Response(
                {'error': '旧密码不正确'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 设置新密码
        user.set_password(new_password)
        user.save()
        
        return Response({'message': '密码修改成功'})
    
    @action(detail=False, methods=['post'])
    def reset_password(self, request):
        """重置密码"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        phone = serializer.validated_data.get('phone')
        code = serializer.validated_data.get('code')
        new_password = serializer.validated_data.get('new_password')
        
        # 验证短信验证码
        now = timezone.now()
        try:
            sms_verification = SmsVerification.objects.filter(
                phone=phone,
                code=code,
                purpose=SmsVerification.Purpose.RESET_PASSWORD,
                is_used=False,
                expires_at__gt=now
            ).latest('created_at')
        except SmsVerification.DoesNotExist:
            return Response(
                {'error': '验证码无效或已过期'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 标记验证码为已使用
        sms_verification.is_used = True
        sms_verification.used_at = now
        sms_verification.save()
        
        # 查找用户
        try:
            user = User.objects.get(phone=phone)
        except User.DoesNotExist:
            return Response(
                {'error': '用户不存在'},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # 设置新密码
        user.set_password(new_password)
        user.save()
        
        return Response({'message': '密码重置成功'})
    
    @action(detail=True, methods=['post'])
    def bind_phone(self, request, pk=None):
        """绑定手机号"""
        user = self.get_object()
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        phone = serializer.validated_data.get('phone')
        code = serializer.validated_data.get('code')
        
        # 验证短信验证码
        now = timezone.now()
        try:
            sms_verification = SmsVerification.objects.filter(
                phone=phone,
                code=code,
                purpose=SmsVerification.Purpose.BIND_PHONE,
                is_used=False,
                expires_at__gt=now
            ).latest('created_at')
        except SmsVerification.DoesNotExist:
            return Response(
                {'error': '验证码无效或已过期'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 检查手机号是否已被其他用户使用
        if User.objects.filter(phone=phone).exclude(id=user.id).exists():
            return Response(
                {'error': '该手机号已被其他用户使用'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 标记验证码为已使用
        sms_verification.is_used = True
        sms_verification.used_at = now
        sms_verification.save()
        
        # 更新用户手机号
        user.phone = phone
        user.save()
        
        return Response({'message': '手机号绑定成功'})